package com.ifp.opengate.boot.filter;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import com.ifp.adapter.common.AdapterCanstants;
import com.ifp.core.context.ClogicContext;
import com.ifp.core.log.Trace;
import com.ifp.opengate.boot.bean.OpenGateRoute;
import com.ifp.opengate.boot.constants.Constants;
import com.ifp.opengate.boot.emum.ErrorEnum;
import com.ifp.opengate.boot.exception.AccessControlException;
import com.ifp.opengate.boot.task.ConnectorCacheDataTask;
import com.ifp.opengate.boot.utils.RedisUtils;

import reactor.core.publisher.Mono;

/**
 * @author liwq
 * @description 接口访问权限校验
 * @date 2021/8/6 15:31
 */
@Component
public class InterfaceAuthorityVerifyGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private ConnectorCacheDataTask connectorCacheDataTask;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Trace.logInfo(Trace.MODULE_FILTER, "InterfaceAuthorityVerifyGlobalFilter start filter....");
        ClogicContext clogicContext = (ClogicContext)exchange.getAttributes().get(Constants.CL_CONTEXT);
        // 请求报文头
        Map<String, Object> dataMap = clogicContext.getDataMap();
        Map<String, Object> headerMap = (Map<String, Object>)dataMap.get(AdapterCanstants.HEADER);
        // 当前请求渠道
        String currentChannel = (String)headerMap.get("channel");
        // 当前请求Route信息
        Route route = (Route)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        OpenGateRoute openGateRoute = connectorCacheDataTask.getRouteOfMap().get(route.getId());

        // 接口抛出异常
        Optional.ofNullable(openGateRoute).orElseThrow(() -> new AccessControlException(ErrorEnum.apiSateError.code(),
            String.format(ErrorEnum.apiSateError.msg(), clogicContext.getTransCode())));

        // Step1: 根据Route信息找出可访问该接口的渠道列表
        List<String> channelList = openGateRoute.getChannelList();

        // Step2: 校验
        if (channelList == null || channelList.size() == 0) {
            throw new AccessControlException(ErrorEnum.accessChannelAuthorizedNoDataError.code(),
                ErrorEnum.accessChannelAuthorizedNoDataError.msg());
        }
        if (channelList != null && channelList.size() > 0) {
            if (!channelList.contains(currentChannel)) {
                throw new AccessControlException(ErrorEnum.accessChannelNotAuthorizedError.code(),
                    ErrorEnum.accessChannelNotAuthorizedError.msg());
            }
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -12;
    }
}
